#ifndef FRACTALVIEWER_H
#define FRACTALVIEWER_H

#include <QPixmap>
#include <QWidget>
#include <QHash>

#include "RenderingThread.h"
#include "palettes.h"

class ColorPalette : public QObject
	{
		Q_OBJECT
		
	public:
		ColorPalette(const char *name);
		
		QString name() const;
		virtual QRgb getColor(double d) =0;
		
	private:
		QString mName;
	};

class DefaultColorPalette : public ColorPalette 
	{
	public:
		DefaultColorPalette();
		
		virtual QRgb getColor(double d);	
	};

class MappingColorPalette : public ColorPalette 
	{
	public:
		MappingColorPalette(const char *name, const TColorMap *map);
		
		virtual QRgb getColor(double d);	
		
	private:
		const TColorMap *map;
	};

class DefaultRenderer : public Renderer
	{
	public:
		DefaultRenderer(ColorPalette *palette, TColorCalc colorCalc);
		
		virtual QRgb render(int iter, double zx, double zy);
	private:
		ColorPalette *palette;
		TColorCalc colorCalc;
	};

class FractalViewer : public QWidget
	{
		// enables slots and signal
		Q_OBJECT
		// defines propeties. This is more for the QTdesigner application
		Q_PROPERTY(double scale READ scale WRITE setScale)
		Q_PROPERTY(int max_itererations READ max_itererations WRITE setMaxiter)
		Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing)
	public:
		FractalViewer(QWidget *parent = 0);
		
		// getters
		double scale() const;
		int maxiter() const;
		bool antialiasing() const;

		// setters
		void setScale(double scale);
		void setMaxiter(int maxiter);
		void setAntialiasing(bool antialiasing);

		// public functions
		void zoom(double zoomFactor);
		void scroll(const QPoint &pos);
		void scroll(int dx, int dy);
		void saveImage();
	protected:
		// bindings to different events
		void paintEvent(QPaintEvent *event);
		void resizeEvent(QResizeEvent *event);
		void keyPressEvent(QKeyEvent *event);
		void wheelEvent(QWheelEvent *event);
		void mouseDoubleClickEvent(QMouseEvent *event);
		void mousePressEvent(QMouseEvent *event);
		void mouseMoveEvent(QMouseEvent *event);
		void mouseReleaseEvent(QMouseEvent *event);
		
	private slots:
		void updatePixmap(const QImage &image, const TRenderParams &renderParams);
		void hideLastMessage();
	
	private:
		static void initialize();

		void rerender();
		void setLastMessage(const QString& message);

		static QList<ColorPalette *> palettes;
		static QHash<QString, TColorCalc> colorCalcs;
		
		// state propeties
		RenderingThread thread;
		QPixmap pixmap;
		QPoint pixmapOffset;
		double pixmapScale;
		QPoint lastDragPos;
		QString lastMessage;
		double centerx;
		double centery;
		QList<ColorPalette *>::Iterator curPalette;
		QHash<QString, TColorCalc>::Iterator curColorCalc;
		
		// member properties
		double mScale;
		int mMaxiter;
		bool mAntialiasing;
	};

#endif

